summaryrefslogtreecommitdiff
path: root/src/pages/posts/[...page].astro
blob: acca0401a8267ee66f9ee69168071d56ec35374c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
---
import type { CollectionEntry } from "astro:content";
import type { GetStaticPaths, Page } from "astro";
import { Icon } from "astro-icon/components";
import PostPreview from "@/components/blog/PostPreview.astro";
import Pagination from "@/components/Paginator.astro";
import { getAllPosts, getUniqueTags, groupPostsByYear } from "@/data/post";
import PageLayout from "@/layouts/Base.astro";
import { collectionDateSort } from "@/utils/date";

export const getStaticPaths = (async ({ paginate }) => {
	const MAX_POSTS_PER_PAGE = 10;
	const MAX_TAGS = 7;
	const allPosts = await getAllPosts();
	const sortedPosts = allPosts.sort(collectionDateSort);
	const uniqueTags = getUniqueTags(sortedPosts).slice(0, MAX_TAGS);
	return paginate(sortedPosts, {
		pageSize: MAX_POSTS_PER_PAGE,
		props: { uniqueTags },
	});
}) satisfies GetStaticPaths;

interface Props {
	page: Page<CollectionEntry<"post">>;
	uniqueTags: string[];
}

const { page, uniqueTags } = Astro.props;

const meta = {
	description: "Read my collection of posts and the things that interest me",
	title: "Posts",
};

const paginationProps = {
	...(page.url.prev && {
		prevUrl: {
			text: "← Previous Page",
			url: page.url.prev,
		},
	}),
	...(page.url.next && {
		nextUrl: {
			text: "Next Page →",
			url: page.url.next,
		},
	}),
};

const groupedByYear = groupPostsByYear(page.data);
const descYearKeys = Object.keys(groupedByYear).sort((a, b) => +b - +a);
---

<PageLayout meta={meta}>
	<div class="mb-6 flex items-center gap-3">
		<h1 class="title">Posts</h1>
		<a class="text-accent" href="/rss.xml" target="_blank">
			<span class="sr-only">RSS feed</span>
			<Icon aria-hidden="true" class="h-6 w-6" focusable="false" name="mdi:rss" />
		</a>
	</div>
	<div class="grid sm:grid-cols-[3fr_1fr] sm:gap-x-8 sm:gap-y-16">
		<div>
			{
				descYearKeys.map((yearKey) => (
					<section aria-labelledby={`year-${yearKey}`}>
						<h2 id={`year-${yearKey}`} class="title text-lg">
							<span class="sr-only">Posts in</span>
							{yearKey}
						</h2>
						<ul class="mt-5 mb-16 space-y-6 text-start">
							{groupedByYear[yearKey]?.map((p) => (
								<li class="grid gap-2 sm:grid-cols-[auto_1fr] sm:[&_q]:col-start-2">
									<PostPreview post={p} />
								</li>
							))}
						</ul>
					</section>
				))
			}
			<Pagination {...paginationProps} />
		</div>
		{
			!!uniqueTags.length && (
				<aside>
					<h2 class="title mb-4 flex items-center gap-2 text-lg">
						Tags
						<svg
							aria-hidden="true"
							class="h-6 w-6"
							fill="none"
							stroke="currentColor"
							stroke-linecap="round"
							stroke-linejoin="round"
							stroke-width="1.5"
							viewBox="0 0 24 24"
							xmlns="http://www.w3.org/2000/svg"
						>
							<path d="M0 0h24v24H0z" fill="none" stroke="none" />
							<path d="M7.859 6h-2.834a2.025 2.025 0 0 0 -2.025 2.025v2.834c0 .537 .213 1.052 .593 1.432l6.116 6.116a2.025 2.025 0 0 0 2.864 0l2.834 -2.834a2.025 2.025 0 0 0 0 -2.864l-6.117 -6.116a2.025 2.025 0 0 0 -1.431 -.593z" />
							<path d="M17.573 18.407l2.834 -2.834a2.025 2.025 0 0 0 0 -2.864l-7.117 -7.116" />
							<path d="M6 9h-.01" />
						</svg>
					</h2>
					<ul class="flex flex-wrap gap-2">
						{uniqueTags.map((tag) => (
							<li>
								<a class="cactus-link flex items-center justify-center" href={`/tags/${tag}/`}>
									<span aria-hidden="true">#</span>
									<span class="sr-only">View all posts with the tag</span>
									{tag}
								</a>
							</li>
						))}
					</ul>
					<span class="mt-4 block sm:text-end">
						<a class="hover:text-link" href="/tags/">
							View all <span aria-hidden="true">→</span>
							<span class="sr-only">blog tags</span>
						</a>
					</span>
				</aside>
			)
		}
	</div>
</PageLayout>